package com.bite.judge.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bite.api.UserExeResult;
import com.bite.api.domain.dto.JudgeSubmitDTO;
import com.bite.api.domain.vo.UserQuestionResultVO;
import com.bite.common.core.constants.Constants;
import com.bite.common.core.constants.JudgeConstants;
import com.bite.common.core.enums.CodeRunStatus;
import com.bite.judge.domain.SandBoxExecuteResult;
import com.bite.judge.domain.UserSubmit;
import com.bite.judge.mapper.UserSubmitMapper;
import com.bite.judge.service.IJudgeService;
import com.bite.judge.service.ISandboxPoolService;
import com.bite.judge.service.ISandboxService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
@Service
public class JudgeServiceImpl implements IJudgeService {
//    @Autowired
//    private ISandboxService sandboxService;
    //只做判断，其余的代码执行啥的用另外一个service
    @Autowired
    private ISandboxPoolService sandboxPoolService;
    @Autowired
    private UserSubmitMapper userSubmitMapper;
    @Override
    public UserQuestionResultVO doJudgeJavaCode(JudgeSubmitDTO judgeSubmitDTO) {
        SandBoxExecuteResult sandBoxExecuteResult=sandboxPoolService
                .exeJavaCode(judgeSubmitDTO.getUserId(), judgeSubmitDTO.getUserCode(),judgeSubmitDTO.getInputList());
        //运行是否成功
        UserQuestionResultVO userQuestionResultVO=new UserQuestionResultVO();
        if(sandBoxExecuteResult!=null
                &&CodeRunStatus.SUCCEED.equals(sandBoxExecuteResult.getRunStatus()
                )){
            //比对直接结果，时间限制，空间限制比对,获取实际结果
           userQuestionResultVO=doJudge(judgeSubmitDTO,sandBoxExecuteResult,userQuestionResultVO);
        }else {
            userQuestionResultVO.setPass(Constants.FALSE);
            if (sandBoxExecuteResult != null) {
                userQuestionResultVO.setExeMessage(sandBoxExecuteResult.getExeMessage());
            } else {
                userQuestionResultVO.setExeMessage(CodeRunStatus.UNKNOWN_FAILED.getMsg());
            }
            //失败了
            userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
        }

        saveUserSubmit(judgeSubmitDTO,userQuestionResultVO);
        return userQuestionResultVO;
    }



    private UserQuestionResultVO doJudge(JudgeSubmitDTO judgeSubmitDTO,
                         SandBoxExecuteResult sandBoxExecuteResult,
                         UserQuestionResultVO userQuestionResultVO){
        List<String> exeOutputList=sandBoxExecuteResult.getOutputList();
        List<String>outputList=judgeSubmitDTO.getOutputList();
        if(outputList.size()!= exeOutputList.size()){
            //当前两个长度都不同,用例未全部通过
            userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
            userQuestionResultVO.setPass(Constants.FALSE);
            userQuestionResultVO.setExeMessage(CodeRunStatus.NOT_ALL_PASSED.getMsg());
            return userQuestionResultVO;
        }
           List<UserExeResult>userExeResultList=new ArrayList<>();
        //进行一个结果的判断，看看用例是否通过
            boolean passed=resultCompare(judgeSubmitDTO,exeOutputList,outputList,userExeResultList);
            //==false
           return assembleUserQuestionResultVO(judgeSubmitDTO,sandBoxExecuteResult,userQuestionResultVO,userExeResultList,passed);
        }

    private boolean resultCompare(JudgeSubmitDTO judgeSubmitDTO,
                                  List<String> exeOutputList,
                                  List<String> outputList,
                                  List<UserExeResult> userExeResultList) {
        boolean passed=true;
        for(int index=0;index< outputList.size();index++){
            String output=outputList.get(index);
            String exeOutput= exeOutputList.get(index);
            String input=judgeSubmitDTO.getInputList().get(index);
            UserExeResult userExeResult=new UserExeResult();
            userExeResult.setInput(input);
            userExeResult.setOutput(output);
            userExeResult.setExeOutput(exeOutput);
            userExeResultList.add(userExeResult);
            if(!output.equals(exeOutput)){
                passed=false;
            }
        }
      return  passed;
    }
    //当用例执行完事之后，我们看看是否全部通过，或者时间/空间
    private UserQuestionResultVO assembleUserQuestionResultVO(JudgeSubmitDTO judgeSubmitDTO,
                                                              SandBoxExecuteResult sandBoxExecuteResult,
                                                        UserQuestionResultVO userQuestionResultVO,
                                                              List<UserExeResult>userExeResultList,
                                                              boolean passed){
        //把准确的是结果(用例通过)的写入列表。
        userQuestionResultVO.setUserExeResultList(userExeResultList);
        if(!passed){
            //封装成一个函数了
            setError(userQuestionResultVO);
            userQuestionResultVO.setExeMessage(CodeRunStatus.NOT_ALL_PASSED.getMsg());
            return userQuestionResultVO;
        }
        //走到这里，就比较一下时间和空间即可,比较大小关系
        if(sandBoxExecuteResult.getUseMemory()>judgeSubmitDTO.getSpaceLimit()){
            setError(userQuestionResultVO);
            userQuestionResultVO.setExeMessage(CodeRunStatus.OUT_OF_MEMORY.getMsg());
            return  userQuestionResultVO;
        }
        //比较时间
        if(sandBoxExecuteResult.getUseTime()>judgeSubmitDTO.getTimeLimit()){
            setError(userQuestionResultVO);
            userQuestionResultVO.setExeMessage(CodeRunStatus.OUT_OF_TIME.getMsg());
            return userQuestionResultVO;
        }
        //这一步说明是正确的，
        userQuestionResultVO.setPass(Constants.TRUE);
        int score=judgeSubmitDTO.getDifficulty()*JudgeConstants.DEFAULT_SCORE;
        userQuestionResultVO.setScore(score);
        return  userQuestionResultVO;

    }
    public void setError(UserQuestionResultVO userQuestionResultVO){
        userQuestionResultVO.setPass(Constants.FALSE);
        userQuestionResultVO.setScore(JudgeConstants.ERROR_SCORE);
    }



    private  void saveUserSubmit(JudgeSubmitDTO judgeSubmitDTO,UserQuestionResultVO userQuestionResultVO){
        UserSubmit userSubmit=new UserSubmit();
        BeanUtil.copyProperties(userQuestionResultVO,userSubmit);
        userSubmit.setUserId(judgeSubmitDTO.getUserId());
        userSubmit.setQuestionId(judgeSubmitDTO.getQuestionId());
        userSubmit.setExamId(judgeSubmitDTO.getExamId());
        userSubmit.setProgramType(judgeSubmitDTO.getProgramType());
        userSubmit.setUserCode(judgeSubmitDTO.getUserCode());
        userSubmit.setCaseJudgeRes(JSON.toJSONString(userQuestionResultVO.getUserExeResultList()));
        userSubmit.setCreateBy(judgeSubmitDTO.getUserId());
        //不用存很多份，存最后一次提交就好
        userSubmitMapper.delete(new LambdaQueryWrapper<UserSubmit>()
                .eq(UserSubmit::getUserId,judgeSubmitDTO.getUserId())
                .eq(UserSubmit::getQuestionId,judgeSubmitDTO.getQuestionId())
                //exam有可能为空
                .isNull(judgeSubmitDTO.getExamId()==null,UserSubmit::getExamId)
                .eq(judgeSubmitDTO.getExamId()!=null,UserSubmit::getExamId,judgeSubmitDTO.getExamId())
        );
        userSubmitMapper.insert(userSubmit);
    }






}

